package com.boarsoft.boar.soagov.svc.action;

import java.io.File;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.BaseConfig;
import com.boarsoft.boar.common.Constants;
import com.boarsoft.boar.dir.DirBiz;
import com.boarsoft.boar.dir.bean.DirTreeNode;
import com.boarsoft.boar.entity.DirInfo;
import com.boarsoft.boar.entity.SoaNexus;
import com.boarsoft.boar.soagov.com.ComBiz;
import com.boarsoft.boar.soagov.entity.ComInfo;
import com.boarsoft.boar.soagov.entity.ObjFaces;
import com.boarsoft.boar.soagov.entity.SvcInfo;
import com.boarsoft.boar.soagov.face.ObjFacesBiz;
import com.boarsoft.boar.soagov.nexus.NexusBiz;
import com.boarsoft.boar.soagov.svc.SvcBiz;
import com.boarsoft.common.Authorized;
import com.boarsoft.common.Util;
import com.boarsoft.common.dao.PagedResult;
import com.boarsoft.common.util.JsonUtil;

@RestController
@RequestMapping("/svc")
public class SvcAction {
	private static final Logger log = LoggerFactory.getLogger(SvcAction.class);

	@Autowired
	private DirBiz dirBiz;
	@Autowired
	private SvcBiz svcBiz;
	@Autowired
	private ComBiz comBiz;
	@Autowired
	private NexusBiz nexusBiz;
	@Autowired
	private ObjFacesBiz objFacesBiz;

	/**
	 * 分页查询某系统下的服务
	 * 
	 * @return
	 */
	@RequestMapping("/list.do")
	@Authorized(code = "svc.list")
	public ReplyInfo<Object> list(String projId, String catalog, String key, String orderBy, int pageNo, int pageSize) {
		PagedResult<SvcInfo> pr = svcBiz.list(projId, catalog, key, orderBy, pageNo, pageSize);
		return new ReplyInfo<Object>(true, pr);
	}

	/**
	 * 服务与组件的关系在FlowAction中保存
	 * 
	 * @return
	 */
	@RequestMapping("/save.do")
	@Authorized(code = "svc.save")
	public ReplyInfo<Object> save(String parent, SvcInfo f) {
		if (Util.strIsEmpty(f.getId())) {
			return this.add(parent, f);
		}
		return this.update(f);
	}

	@RequestMapping("/add.do")
	@Authorized(code = "svc.add")
	public ReplyInfo<Object> add(String parent, SvcInfo f) {
		// 检查parent是否存在，取出path拼接
		DirInfo d = new DirInfo();
		d.setParentId(parent);
		// 设置这个目录在目录树上的路径
		if (BaseConfig.DIR_ROOT.equals(parent)) {
			d.setPath("/");
			d.setLevel(1);
		} else {
			DirInfo p = dirBiz.get(parent);
			d.setLevel(p.getLevel() + 1);
			if ("/".equals(p.getPath())) {
				d.setPath(String.format("%s%s", p.getPath(), p.getId()));
			} else {
				d.setPath(String.format("%s/%s", p.getPath(), p.getId()));
			}
		}
		// o.setId(id); // id是自动生成的
		d.setCode(f.getCode());
		d.setName(f.getName());
		// o.setLevel(level); // level是在add当中+1的
		// o.setChildCount(childCount); //初始值已为0
		d.setType(DirInfo.TYPE_SVC);
		// d.setDesc(desc);

		// 服务对象本身
		f.setStatus(SvcInfo.STATUS_NOUSE);

		// 无论这个服务是否真的有流程，都保存一个对应的SUBFLOW组件
		// 除非这个SUBFLOW在其它流程中被显示引用，否则这个组件在树上看不到
		ComInfo c = new ComInfo();
		c.setCode(f.getCode());
		c.setName(f.getName());
		c.setType(ComInfo.TYPE_SUBFLOW);
		c.setFaceId(f.getFaceId());
		c.setImpl(f.getImpl());
		c.setVer(f.getVer());
		c.setStatus(ComInfo.STATUS_NOUSE);
		// c.setJson(json);
		c.setMemo(f.getMemo());
		ReplyInfo<Object> ro = svcBiz.add(d, f, c); // 这里会保存svc与app的关系
		if (ro.isSuccess()) {
			DirTreeNode dtn = new DirTreeNode((DirInfo) ro.getData());
			return new ReplyInfo<Object>(true, dtn);
		}
		return new ReplyInfo<Object>(ro.getData());
	}

	/**
	 * 服务与组件的关系在FlowAction中保存
	 * 
	 * @return
	 */
	@RequestMapping("/update.do")
	@Authorized(code = "svc.update")
	public ReplyInfo<Object> update(SvcInfo o) {
		// 只能改DirInfo
		DirInfo d = dirBiz.get(o.getId());
		d.setCode(o.getCode());
		d.setName(o.getName());
		// d.setDesc(desc);
		// d.setPath(path); //path是由code决定

		//
		SvcInfo f = svcBiz.get(o.getId());
		f.setCode(o.getCode());
		f.setName(o.getName());
		f.setType(o.getType());
		f.setCatalog(o.getCatalog());
		f.setFaceId(o.getFaceId());
		f.setImpl(o.getImpl());
		f.setVer(o.getVer());
		f.setUrl(o.getUrl()); // 访问URL
		f.setPath(o.getPath());// 导出路径
		f.setStatus(o.getStatus());
		f.setMemo(o.getMemo());

		// 保存一个组件，这个组件在树上看不到，目的是简化依赖关系的保存问题
		ComInfo c = comBiz.get(o.getId());
		// c.setAppId(appId);
		// c.setCode(code);
		c.setName(o.getName());
		// c.setType(ComInfo.TYPE_SUBFLOW);
		c.setFaceId(o.getFaceId());
		c.setImpl(o.getImpl());
		c.setVer(o.getVer());
		// c.setStatus(ComInfo.STATUS_NOUSE);
		// c.setJson(json);
		f.setMemo(o.getMemo());
		ReplyInfo<Object> ro = svcBiz.update(d, f, c);
		if (ro.isSuccess()) {
			DirTreeNode dtn = new DirTreeNode((DirInfo) ro.getData());
			return new ReplyInfo<Object>(true, dtn);
		}
		return new ReplyInfo<Object>(ro.getData());
	}

	@RequestMapping("/delete.do")
	@Authorized(code = "svc.delete")
	public ReplyInfo<Object> delete(String id) {
		// 获取服务信息，判断是否有FLOW
		SvcInfo o = svcBiz.get(id);
		if (SvcInfo.TYPE_FLOW == o.getType()) {
			// 有FLOW就删除对应的FLOW
			DirInfo d = dirBiz.get(id);// svcId与dirId相同
			StringBuilder sb = new StringBuilder();
			sb.append(BaseConfig.PATH_PRIVATE).append(d.getPath());
			String p = sb.toString();
			try {
				log.info("Delete flow diagram {}", p);
				File f = new File(p);
				do {
					log.info("Delete direcotory {}", d.getPath());
					if (!f.delete()) {
						log.warn("Can not delete direcotory {}", d.getPath());
					}
					f = f.getParentFile();
				} while (f.list().length == 0);
			} catch (Exception e) {
				log.error("Error on delete flow diagram {}", p, e);
				return Constants.REPLY_ERROR_INTERNAL;
			}
		}
		svcBiz.delete(id); // 同时删除：DIR，SVC，COM
		return ReplyInfo.SUCCESS;
	}

	@RequestMapping("/get.do")
	// @Authorized(code = "svc.get")
	public String get(String id) {
		SvcInfo fo = svcBiz.get(id);
		StringBuilder sb = new StringBuilder();
		sb.append("{ \"success\": true, \"data\": ");
		sb.append(JsonUtil.from(fo)).append(", \"byMe\": { \"0\": {}");
		List<SoaNexus> byLt = nexusBiz.listByMe(id);
		for (SoaNexus n : byLt) {
			sb.append(", \"").append(n.getObjId1()).append("\": ");
			sb.append(JsonUtil.from(n, "face,obj0,lib"));
		}
		sb.append(" }, \"onMe\": { \"0\": {}");
		List<SoaNexus> onLt = nexusBiz.listOnMe(id);
		for (SoaNexus n : onLt) {
			sb.append(", \"").append(n.getObjId1()).append("\": ");
			sb.append(JsonUtil.from(n, "face,obj1,lib"));
		}
		sb.append(" }, \"faces\": { \"0\": {}");
		PagedResult<ObjFaces> cfPr = objFacesBiz.list(id, "", "", "", "", 1, 9999);
		for (ObjFaces n : cfPr.getList()) {
			sb.append(", \"").append(n.getFaceId()).append("\": ");
			sb.append(JsonUtil.from(n.getFace()));
		}
		sb.append(" }}");
		return sb.toString();
	}

	/**
	 * 修改服务状态，但并不开关服务
	 * 
	 * @return
	 */
	@RequestMapping("/status.do")
	@Authorized(code = "svc.status")
	public ReplyInfo<Object> status(String id, short status) {
		if (svcBiz.status(id, status)) {
			return ReplyInfo.SUCCESS;
		}
		return Constants.REPLY_WARN_INVALID;
	}
}